﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MIC = Microsoft.IdentityModel.Claims;
using SSP = System.Security.Principal;
using SWS = System.Web.Security;
using CodeCamp.Infrastructure;
using CodeCamp.Model;


namespace CodeCamp.Controllers
{
    public class ClaimsLocalHandler
    {
        CodeCampDataRepository _ccdr;
        string _eventShortName;
        IDefaultValueProvider _valueProvider;

        public ClaimsLocalHandler(CodeCampDataRepository ccdr, IDefaultValueProvider valueProvider, string eventShortName)
        {
            if (ccdr == null)
                throw new ArgumentNullException("ccdr");

            _ccdr = ccdr;
            _eventShortName = eventShortName;
            _valueProvider = valueProvider;
        }

        private string _defaultEventShortName;
        protected string DefaultEventShortName
        {
            get
            {
                if (_defaultEventShortName == null)
                {
                    _defaultEventShortName = _valueProvider.GetDefaultStringValue(Constants.Tags.defaultEventShortName, Constants.Defaults.defaultEventShortName);
                }
                return _defaultEventShortName;
            }
        }

        private SiteUser GetSiteUser(MIC.IClaimsIdentity claimsIdent, bool userIsOnline)
        {
            SiteUser siteUser = null;
            if (claimsIdent != null)
            {
                int claimCount;
                string identityProvider = null;
                string claimType = null;
                string claim = null;

                MIC.Claim providerClaim = ControllerBase.GetFirstClaim(claimsIdent.Claims, CodeCampDataRepository.ClaimTypes.identityprovider_2010, out claimCount);
                MIC.Claim identityClaim = ControllerBase.GetFirstClaim(claimsIdent.Claims, CodeCampDataRepository.ClaimTypes.nameidentifier_2005, out claimCount);
                if ((providerClaim != null) && (identityClaim != null))
                {
                    identityProvider = providerClaim.Value;
                    claimType = identityClaim.ClaimType;
                    claim = identityClaim.Value;
                }
                else
                {
                    MIC.Claim nameClaim = ControllerBase.GetFirstClaim(claimsIdent.Claims, CodeCampDataRepository.ClaimTypes.name_2005, out claimCount);
                    if (nameClaim != null)
                    {
                        identityProvider = CodeCampDataRepository.IdentityProviders.CodeCamp;
                        claimType = CodeCampDataRepository.ClaimTypes.username;
                        claim = nameClaim.Value;
                    }
                }

                if (!string.IsNullOrWhiteSpace(identityProvider) && !string.IsNullOrWhiteSpace(claimType) && !string.IsNullOrWhiteSpace(claim))
                {
                    siteUser = _ccdr.GetSiteUser(identityProvider, claimType, claim, userIsOnline, false);
                }
            }
            return siteUser;
        }

        //TO DO: Pass in event short name from URL and get event-specific roles
        internal Nullable<int> SetApplicationClaims(MIC.ClaimsPrincipal claimsPrincipal, bool userIsOnline)
        {
            Nullable<int> localClaimsAdded = null;

            if (claimsPrincipal != null)
            {
                localClaimsAdded = -1;
                var claimsIdent = claimsPrincipal.Identity as MIC.IClaimsIdentity;
                if (claimsIdent != null)
                {
                    localClaimsAdded = 0;
                    SiteUser siteUser = GetSiteUser(claimsIdent, userIsOnline);
                    if ((siteUser != null) && (siteUser.Id != 0))
                    {
                        List<string> localRoleClaims = new List<string>();
                        List<MIC.Claim> existingClaims = ControllerBase.GetClaimsOfType(claimsIdent.Claims, MIC.ClaimTypes.Role);
                        foreach (MIC.Claim claim in existingClaims)
                        {
                            if (claim.Issuer == CodeCampDataRepository.ClaimIssuers.LOCAL_AUTHORITY)
                            {
                                localRoleClaims.Add(claim.Value);
                            }
                        }


                        List<string> siteRoles = _ccdr.GetSiteUserSiteRoles(siteUser.Id);
                        foreach (string roleName in siteRoles)
                        {
                            if (!localRoleClaims.Contains(roleName))
                            {
                                claimsIdent.Claims.Add(new MIC.Claim(MIC.ClaimTypes.Role, roleName));
                            }
                        }

                        string eventShortName = _eventShortName;
                        if (string.IsNullOrWhiteSpace(_eventShortName))
                            eventShortName = DefaultEventShortName;

                        Event ccEvent = _ccdr.GetEvent(eventShortName, false);
                        if (ccEvent != null)
                        {
                            List<string> eventRoles = _ccdr.GetSiteUserEventRoles(siteUser.Id, ccEvent.Id);
                            foreach (string roleName in eventRoles)
                            {
                                if (!localRoleClaims.Contains(roleName))
                                {
                                    claimsIdent.Claims.Add(new MIC.Claim(MIC.ClaimTypes.Role, roleName));
                                }
                            }
                        }
                    }
                }
            }

            return localClaimsAdded;
        }

    }
}